<?php
//微信用户相关操作

namespace App\Services\Wx;

use App\Common\CommonConst;
use App\Models\MonitorModel;
use App\Models\AuthedLogModel;
use App\Models\DinnerLogModel;
use App\Models\ReceiversModel;
use App\Models\RestaurantManageModel;
use App\Models\RestaurantModel;
use App\Repositories\DinnerLogRepository;
use App\Repositories\ReceiversRepository;
use App\Repositories\WxUsersRepository;
use App\Services\ActivityService;
use App\Services\ReceiverService;
use App\Services\CouponService;
use App\Services\SubsidyBillService;
use Carbon\Carbon;
use EasyWeChat\Pay\Application;
use Illuminate\Support\Facades\Auth;

class UserService
{
    const AUTH_ALLOW = 1;       // 扫描二维码核销时是否有权限核销，1为可核销二维码，2为不能核销二维码（不是商家后台管理员）
    const AUTH_FORBIDDEN = 2;

    const QRCODE_CANUSE = 0;   // 0、可使用 1、认证过期，2、没资格领取，3、已使用完，4、使用方式不正确（更换为优惠券券方式，只能使用一种方式）
    const QRCODE_EXPIRED = 1;
    const QRCODE_FORBIDDEN = 2;
    const QRCODE_USED = 3;
    const QRCODE_TYPE_ERROR = 4;

    const QRCODE_DESC = [
        self::QRCODE_CANUSE => '',
        self::QRCODE_EXPIRED => '受助老人的身份认证已经过期，暂无其他可用的助老餐券及二维码，希望您能协助受助老人重新认证~',
        self::QRCODE_FORBIDDEN => '受助老人已取消资格，不能再享受优惠补贴',
        self::QRCODE_USED => '该二维码今天已经使用完，请明天再来！',
        self::QRCODE_TYPE_ERROR => '该二维码已失效，支付方式已更换为优惠券券，两种方式只能二选一，请使用手机支付核销优惠券~',
    ];

    /**
     * 检查受助者状态
     * @param $receiverId
     * @return array
     */
    public function checkReceiverInfo ($receiverId, $activityId)
    {
        $status = self::QRCODE_CANUSE;
        $desc = self::QRCODE_DESC[$status];
        $receiver = ReceiversModel::find($receiverId);
        $couponMoney = MonitorModel::where('id', $activityId)
            ->value('coupon_amount');
        if ($receiver) {
            if (time() > strtotime($receiver['auth_end_date'])) {
                $status = self::QRCODE_EXPIRED;
            } else if ($receiver['type'] == ReceiversModel::TYPE_COUPON) {
                $status = self::QRCODE_TYPE_ERROR;
            } else if ($receiver['receiver_status'] == ReceiversModel::RECEIVE_STATUS_DISABLE) {
                $status = self::QRCODE_FORBIDDEN;
            } else {
                $status = $this->checkQrcodeUsedAll($receiver, $activityId);
            }
            $desc = self::QRCODE_DESC[$status];
        }
        return [
            'status' => $status,
            'receiver_name' => $receiver['name'],
            'money' => $couponMoney,
            'desc' => $desc
        ];
    }

    public function checkQrcodeUsedAll ($receiver, $activityId)
    {
        $status = self::QRCODE_CANUSE;
        $dailyReceiveNum = $receiver->activity['coupon_daily_receive_num'];
        $dinnerLogRepo = new DinnerLogRepository();
        $dinnerLogCount = $dinnerLogRepo->getReceiverDailyAmount($receiver, $activityId);
        if ($dinnerLogCount == $dailyReceiveNum) {
            $status = self::QRCODE_USED;
        }
        return $status;
    }

    public function checkRestaurantManageAuth ($openid, $activityId)
    {
        $authStatus = self::AUTH_FORBIDDEN;
        $data = [];
        $restaurantCount = RestaurantManageModel::where('openid', $openid)
            ->where('activity_id', $activityId)
            ->where('status', RestaurantManageModel::STATUS_ENABLE)
            ->count();
        if ($restaurantCount > 0) {
            $authStatus = self::AUTH_ALLOW;
        } else {
            $data['desc'] = '该餐厅管理员无权限操作';
        }
        $data['authStatus'] = $authStatus;
        return $data;
    }

    /**
     * 保存微信用户
     * @param $data
     * @return array
     */
    public static function saveUser($data = [])
    {
        if (empty($data['openid'])) {
            return resultError('参数缺失');
        }
        //验证是否已入库过
        $userRepo = new WxUsersRepository();
        $userRepo->buildQuery([
            'openid' => $data['openid'],
        ]);
        $exist = $userRepo->getRow();
        if ($exist) {
            return resultSuccess([
                'id' => $exist->id,
            ]);
        }
        $userId = $userRepo->save([
            'openid' => $data['openid'],
        ]);
        if (!$userId) {
            return resultError('保存失败');
        }

        return resultSuccess([
            'id' => $userId,
        ]);

    }

    /**
     * 获取微信用户信息
     * @param $query
     * @return array
     */
    public static function getUserInfo($query = [])
    {
        $userRepo = new WxUsersRepository();
        $userRepo->buildQuery($query);

        return $userRepo->getRow();
    }

    /**
     * 根据id获取用户信息
     * @param $id
     * @return array
     */
    public static function getUsreInfoById($id)
    {
        return self::getUserInfo([
            'id' => $id,
        ]);
    }

    /**
     * 微信用户授权登录
     * @param $code
     * @return array
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     */
    public static function login($code)
    {
        $wxApp = new \App\Services\Wx\WxMiniApp();
        $wxUserRes = $wxApp->getUserOpenByCode($code);
        if ($wxUserRes['errcode']) {
            return resultError('验证失败');
        }
        $wxUserRes = $wxUserRes['data'];
        $openid = $wxUserRes['openid'];
        //根据openid查询是否已保存过
        $userRepo = new WxUsersRepository();
        $userRepo->buildQuery([
            'openid' => $openid,
        ]);
        $userInfo = $userRepo->getRow();
        if (!$userInfo) {
            //保存用户
            $userId = $userRepo->save([
                'openid' => $openid,
            ]);
            if (!$userId) {
                return resultError('验证失败');
            }
            $userRepo->buildQuery([
                'id'        => $userId,
                'useMaster' => 1,
            ]);
            $userInfo = $userRepo->getRow();
        }
        //生成密钥
        Auth::setUser($userInfo);
        $token = $userInfo->createToken(CommonConst::GBD_PLATFORM);
        // 获取授权状态
        $receiver = ReceiversModel::where('openid', $openid)
            ->select('auth_status', 'id')
            ->first();
        if ($receiver) {
            $authStatus = $receiver['auth_status'];
            // 获取最后一次登录的活动id
            $lastActivityId = AuthedLogModel::where('receiver_id', $receiver['id'])
                ->value('activity_id');
        }
        $output = [
            'token'       => $token->plainTextToken,
            'token_type'  => 'Bearer',
            'last_activity_id' => $lastActivityId ?? '',
            'session_key' => $wxUserRes['session_key'],
            'openid'      => $wxUserRes['openid'],
            'auth_status' => $authStatus ?? 2
        ];

        return resultSuccess($output);
    }

    /**
     * 验证是否需要身份校验
     * @param $openId
     * @return array
     */
    public static function verifyNeedReal($openId, $activityId)
    {
        $output = [
            'need_verify_real' => 0, //是否需要验证真身
            'access_token'     => WxConfig::getToken(), //微信token
        ];
        //获取活动领取人信息
        $receiverInfo = ReceiverService::getRow([
            'openid'      => $openId,
            'activity_id' => $activityId,
        ]);
        if (!$receiverInfo) {
            $output['need_verify_real'] = 1;
            return resultSuccess($output);
        }

        return resultSuccess($output);
    }

    /**
     * 验证用户是否可领取
     * @param $openId
     * @param $activityId
     * @return array
     */
    public static function verifyUserReceived($openId, $activityId)
    {
        $receiverInfo = ReceiverService::getRow([
            'activity_id' => $activityId,
            'openid'      => $openId,
            'getMaster'   => 1, //使用主库
        ]);
        if (!$receiverInfo) {
            return resultError('用户未进行身份认证', 401);
        }

        if (!$receiverInfo || !$receiverInfo['receive_num']) {
            return resultError('无可领券');
        }
        if ($receiverInfo['receive_num'] <= $receiverInfo['received_num']) {
            return resultError('已全部领取过了', 402, [
                'receive_num'    => $receiverInfo['receive_num'],
                'received_num'   => $receiverInfo['received_num'],
                'unreceived_num' => 0,
            ]);
        }
        //        //获取此用户是否已领取过
        //        $couponTotal = CouponService::getTotal([
        //            'receiver_id' => $receiverInfo['id'],
        //            'activity_id' => $activityId,
        //        ]);
        //        if ($couponTotal) {
        //            return resultError('您已经领取过了');
        //        }
        //获取用户是否有未使用的券
        $unUseCouponNum = CouponService::getTotal([
            'activity_id'    => $activityId,
            'receiver_id'    => $receiverInfo['id'],
            'consume_status' => 1,
        ]);
        if ($unUseCouponNum) {
            return resultError('您还有未核销的券', 403);
        }

        return resultSuccess([
            'receive_id'     => $receiverInfo['id'],
            'receive_num'    => $receiverInfo['receive_num'],
            'received_num'   => $receiverInfo['received_num'],
            'unreceived_num' => $receiverInfo['receive_num'] - $receiverInfo['received_num'],
        ]);
    }

    /**
     * 用户领取消费券
     * @param $wxUserId
     * @param $activityId
     * @return array
     */
    public static function userAuthReceive($wxUserId, $activityId)
    {
        //获取用户
        $userInfo = UserService::getUsreInfoById($wxUserId);
        if (!$userInfo || !$userInfo->openid) {
            return resultError('用户信息有误');
        }
        $openid = $userInfo->openid;
        //获取活动信息
        $activityInfo = ActivityService::getRow([
            'id' => $activityId,
        ]);
        if (!$activityInfo) {
            return resultError('活动有误');
        }
        if (!$activityInfo['stock_ids'] || !$activityInfo['every_receive_num']) {
            return resultError('活动消费券配置有误');
        }
        $stockIds = explode(',', $activityInfo['stock_ids']);
        //验证用户是否可领券
        $verRes = self::verifyUserReceived($openid, $activityId);
        if ($verRes['errcode']) {
            return $verRes;
        }
        $verRes = $verRes['data'];
        //领取消费券流程
        $receiveRes = \App\Services\Wx\CouponService::userReceiveCoupon($openid, $stockIds,
            $activityInfo['every_receive_num'], $activityId, $verRes['receive_id']);
        if (!$receiveRes) {
            return resultError('领取失败');
        }

        return resultSuccess([], '领取成功');
    }

    /**
     * 用户领取验证展示信息
     * @param $wxUserId
     * @param $activityId
     * @return array
     */
    public static function verifyUserReceiveShow($wxUserId, $activityId)
    {
        if (!$activityId) {
            return resultError('参数缺失');
        }
        //是否需要校验
        $userInfo = self::getUsreInfoById($wxUserId);
        if (!$userInfo) {
            return resultError('用户有误');
        }
        $output = [
            'un_use_coupon'  => 0, //是否有未使用的券，
            'receive_num'    => 0, //总领取份数
            'received_num'   => 0, //已领取份数
            'unreceived_num' => 0, //未领取分数
        ];
        $openid = $userInfo->openid;
        $verRes = UserService::verifyUserReceived($openid, $activityId);
        if ($verRes['errcode'] == 403) {
            $output['un_use_coupon'] = 1;

            return resultSuccess($output);
        }
        if ($verRes['errcode']) {
            return resultError($verRes['errmsg']);
        }
        $verRes = $verRes['data'];
        $output['receive_num'] = $verRes['receive_num'];
        $output['received_num'] = $verRes['received_num'];
        $output['unreceived_num'] = $verRes['unreceived_num'];

        return resultSuccess($output);
    }

    /**
     * 设置券过期通知状态
     * @param $wxUserId
     * @param $activityId
     * @return array
     */
    public static function setCouponExpireNotice($wxUserId, $activityId = 0)
    {
        //获取用户
        $userInfo = self::getUsreInfoById($wxUserId);
        if (!$userInfo || !$userInfo->openid) {
            return resultError('用户信息有误');
        }
        $openid = $userInfo->openid;
        $receiverInfo = ReceiverService::getRow([
            'activity_id' => $activityId,
            'openid'      => $openid,
        ]);
        if (!$receiverInfo) {
            return resultError('用户有误');
        }
        $res = ReceiverService::saveAllowExpireNotice($receiverInfo['id'], 1);
        if ($res['errcode']) {
            return resultError($res['errmsg']);
        }

        return resultSuccess([], $res['errmsg']);
    }

    /**
     * 保存用户身份校验信息
     * @param $activityId
     * @param $realData
     * @param $wxUserId
     * @return array
     */
    public static function saveUserReal($activityId, $realId, $wxUserId)
    {
        if (!$activityId) {
            return resultError('参数有误');
        }
        if (!$realId) {
            return resultError('未获取到领取人标识');
        }
        //查询领券人
        $receiverInfo = ReceiverService::getRow([
            'activity_id' => $activityId,
            'real_id'     => $realId,
        ]);
        if (!$receiverInfo) {
            return resultError('未查询到领取人信息');
        }
        //获取用户
        $userInfo = self::getUsreInfoById($wxUserId);
        if (!$userInfo || !$userInfo->openid) {
            return resultError('用户信息有误');
        }
        $openid = $userInfo->openid;
        //领券人关联openid
        $res = (new ReceiversRepository)->updateFields($receiverInfo['id'], [
            'openid' => $openid,
            'auth_status' => ReceiversModel::RECEIVE_STATUS_ENABLED,
            'auth_start_date' => date('Y-m-d H:i:s'),
            'auth_end_date' => date('Y-m-d', strtotime('+90 days', time())) . ' 23:59:59'
        ]);
        if (!$res) {
            return resultError('保存失败');
        }
        return resultSuccess([
            'real_id' => $realId
        ], '保存成功');
    }

    public static function getRealId ($realData)
    {
        $realData = json_decode($realData, true);
        if (!$realData) {
            return resultError('数据格式有误');
        }
        $realData['attach'] = str_replace('{', '[', $realData['attach']);
        $realData['attach'] = str_replace('}', ']', $realData['attach']);
        $attach = str_replace('“', '"', $realData['attach']);
        $attach = json_decode($attach, true);
        $realId = $attach[0] ?? 0;
        return $realId;
    }

    /**
     * 补贴活动 用户领取验证展示信息
     * @param $wxUserId
     * @param $activityId
     * @return array
     */
    public static function verifyUserReceiveSubsidyShow($wxUserId, $activityId)
    {
        if (!$activityId) {
            return resultError('参数缺失');
        }
        //是否需要校验
        $userInfo = self::getUsreInfoById($wxUserId);
        if (!$userInfo) {
            return resultError('用户有误');
        }
        $output = [
            'receive_status' => 1, //是否可领取: 1.可领取；2.不可领取;
        ];
        $openid = $userInfo->openid;
        $verRes = UserService::verifyUserReceivedSubsidy($openid, $activityId);
        if ($verRes['errcode']) {
            return resultError($verRes['errmsg']);
        }

        return resultSuccess($output);
    }


    /**
     * 补贴活动 验证用户是否可领取
     * @param $openId
     * @param $activityId
     * @return array
     */
    public static function verifyUserReceivedSubsidy($openId, $activityId)
    {
        $receiverInfo = ReceiverService::getRow([
            'activity_id' => $activityId,
            'openid'      => $openId,
            'getMaster'   => 1, //使用主库
        ]);
        if (!$receiverInfo) {
            return resultError('用户未进行身份认证', 401);
        }

        if (!$receiverInfo || !$receiverInfo['subsidy_amount']) {
            return resultError('无可领补贴');
        }
        //判断用户是否已领过
        $billInfo = SubsidyBillService::getRow([
            'activity_id' => $activityId,
            'receiver_id' => $receiverInfo['id'],
            'status_in' => [1, 2, 3, 4], //失败状态不取
        ]);
        if ($billInfo) {
            switch ($billInfo['status']) {
                case 3: //转账处理中
                case 4: //转账成功
                    return resultError('您已经领取过了');
            }
        }

        return resultSuccess([
            'receive_info' => $receiverInfo, //领取人信息
            'bill_info'    => $billInfo, //单据信息
        ]);
    }

    /**
     * 补贴活动，用户领取消费券
     * @param $wxUserId
     * @param $activityId
     * @return array
     */
    public static function userAuthReceiveSubsidy($wxUserId, $activityId)
    {
        //获取用户
        $userInfo = UserService::getUsreInfoById($wxUserId);
        if (!$userInfo || !$userInfo->openid) {
            return resultError('用户信息有误');
        }
        $openid = $userInfo->openid;
        //获取活动信息
        $activityInfo = ActivityService::getRow([
            'id' => $activityId,
        ]);
        if (!$activityInfo) {
            return resultError('活动有误');
        }
        //验证用户是否可补贴
        $verRes = self::verifyUserReceivedSubsidy($openid, $activityId);
        if ($verRes['errcode']) {
            return $verRes;
        }
        $receiveInfo = $verRes['data']['receive_info']; //领取人信息
        $billInfo = $verRes['data']['bill_info']; //上次已生成的转账单据

        //创建转账单据
        $receiveRes = SubsidyWxService::createSubsidyBill($activityId, $receiveInfo['id'], $openid,
            $receiveInfo['name'], $receiveInfo['subsidy_amount'], $activityInfo['title'], $billInfo);
        if ($receiveRes['errcode']) {
            return resultError('领取失败');
        }

        return resultSuccess($receiveRes['data'], '创建转账单据成功');
    }


}
